﻿using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

//麦克哈德
namespace Microhard.Core
{
    public static class IoC
    {
        private static readonly object _SyncRoot = new Object();
        private static IUnityContainer _Container;

        /// <summary>
        /// 获取或设置用于 Unity 容器。
        /// </summary>
        /// <remarks>
        /// 第一次获取本属性时会触发自动构建 Unity 容器。
        /// </remarks>
        public static IUnityContainer Container
        {
            get
            {
                if (_Container == null)
                {
                    lock (_SyncRoot)
                    {
                        if (_Container == null)
                        {
                            BuiltUpContainer();
                        }
                    }
                }

                return _Container;
            }
            set { _Container = value; }
        }

        private static event EventHandler _BeforeContainerBuiltUp;

        /// <summary>
        /// 创建 Unity 容器前会触发本事件。
        /// </summary>
        public static event EventHandler BeforeContainerBuiltUp
        {
            add { _BeforeContainerBuiltUp += value; }
            remove { _BeforeContainerBuiltUp -= value; }
        }

        private static void InvokeBeforeContainerBuiltUp(EventArgs e)
        {
            if (_BeforeContainerBuiltUp != null)
            {
                _BeforeContainerBuiltUp(null, e);
            }
        }

        private static event EventHandler _AfterContainerBuiltUp;

        /// <summary>
        /// 创建 Unity 容器后会触发本事件。
        /// </summary>
        public static event EventHandler AfterContainerBuiltUp
        {
            add { _AfterContainerBuiltUp += value; }
            remove { _AfterContainerBuiltUp -= value; }
        }

        private static void InvokeAfterContainerBuiltUp(EventArgs e)
        {
            if (_AfterContainerBuiltUp != null)
            {
                _AfterContainerBuiltUp(null, e);
            }
        }

        /// <summary>
        /// 重新初始化 Unity 容器。
        /// </summary>
        public static void ReInitialContainer()
        {
            lock (_SyncRoot)
            {
                _Container = null;
                BuiltUpContainer();
            }
        }

        private static void BuiltUpContainer()
        {
            InvokeBeforeContainerBuiltUp(null);
            _Container = new UnityContainer();
            _Container.LoadConfiguration();
            InvokeAfterContainerBuiltUp(null);
        }

        /// <summary>
        /// 获取一个指定类型的实例。
        /// </summary>
        /// <param name="type">要获取的实例的类型。</param>
        /// <returns>获取的实例。</returns>
        public static object Resolve(Type type)
        {
            return Container.Resolve(type);
        }

        /// <summary>
        /// 获取一个指定类型和名称的实例。
        /// </summary>
        /// <param name="type">要获取的实例的类型。</param>
        /// <param name="name">要获取的实例的名称。</param>
        /// <returns>获取的实例。</returns>
        public static object Resolve(Type type, string name)
        {
            return Container.Resolve(type, name);
        }

        ///<summary>
        /// 获取一个指定类型的实例。
        /// </summary>
        /// <typeparam name="T">要获取的实例的类型。</typeparam>
        /// <returns>获取的实例。</returns>
        public static T Resolve<T>()
        {
            return Container.Resolve<T>();
        }

        /// <summary>
        /// 获取一个指定类型和名称的实例。
        /// </summary>
        /// <typeparam name="T">要获取的实例的类型。</typeparam>
        /// <param name="name">要获取的实例的名称。</param>
        /// <returns>获取的实例。</returns>
        public static T Resolve<T>(string name)
        {
            return Container.Resolve<T>(name);
        }

        public static bool IsRegistered<T>()
        {
            return Container.IsRegistered<T>();
        }

        public static bool IsRegistered(Type typeToCheck)
        {
            return Container.IsRegistered(typeToCheck);
        }

        public static bool IsRegistered<T>(string name)
        {
            return Container.IsRegistered<T>(name);
        }

        public static bool IsRegistered(Type typeToCheck, string name)
        {
            return Container.IsRegistered(typeToCheck, name);
        }
    }
}